#ifndef TCPSTRUCT_H
#define TCPSTRUCT_H

#include <QHostAddress>
#include <QDateTime>
#include <QtEndian>
#include <QMutex>

#include "ctagdata.h"

#define DEF_FAIL 0
#define DEF_SUCCESS 1

struct SClientCfg
{
    int m_nFd;              //linux文件描述符
    int m_nPort;            //端口
    QHostAddress m_addr;    //ip
    QString m_sGuid;        //Guid ip:port
    QString m_sName;        //客户端名称

    SClientCfg()
    {
        m_nFd = -1;
        m_nPort = 0;
    }
    SClientCfg(int _nFd, int _nPort, uint32_t _nIP)
    {
        m_nFd = _nFd;
        m_nPort = _nPort;
        if (m_nPort < 0) m_nPort = 0;
        if (m_nPort > 65535) m_nPort = 65535;
        m_addr = QHostAddress(_nIP);
        //m_sGuid = m_addr.toString() + ":" + QString::number(m_nPort);
        m_sGuid = m_addr.toString();
    }
};

//报文处理基类
class CKYTXBase
{
public:
    CKYTXBase() {}
    //数据类型
    enum enumCmdType
    {
        enCmdTags = 101,        //测点列表
        enCmdRealData = 102,    //实时数据
        enCmdWarning = 103,     //报警
        enCmdStatus = 104,      //状态数据
        enCmdHistory = 105,     //历史数据
        enCmdLog = 106,         //日志

        //测点列表
        enCmdTagsCheck = 1,     //点表校验
        enCmdTagsInfo = 2,      //测点信息
    };
protected:
    inline qint16 getQint16(quint8 nIn[2])      { return qFromBigEndian<qint16>(nIn); }
    inline quint16 getQuint16(quint8 nIn[2])    { return qFromBigEndian<quint16>(nIn); }
    inline qint32 getQint32(quint8 nIn[4])      { return qFromBigEndian<qint32>(nIn); }
    inline quint32 getQuint32(quint8 nIn[4])    { return qFromBigEndian<quint32>(nIn); }
    inline qint64 getQint64(quint8 nIn[8])      { return qFromBigEndian<qint64>(nIn); }
    inline quint64 getQuint64(quint8 nIn[8])    { return qFromBigEndian<quint64>(nIn); }
    inline float getFloat(quint8 nIn[4])
    {
        quint32 nValue = qFromBigEndian<quint32>(nIn);
        float fValue = 0.00f;
        memcpy(&fValue, &nValue, sizeof(quint32));
        return fValue;
    }
    inline double getDouble(quint8 nIn[8])
    {
        quint64 nValue = qFromBigEndian<quint64>(nIn);
        double dValue = 0.00f;
        memcpy(&dValue, &nValue, sizeof(quint64));
        return dValue;
    }
};

//通信协议报文头
class CKYTXHeader : public CKYTXBase
{
public:
    enum enumHeader
    {
        enHeader1 = 0x58,   //'X'
        enHeader2 = 0x54,   //'T'
        enHeader3 = 0x59,   //'Y'
        enHeader4 = 0x4b,   //'K'
    };
public:
	CKYTXHeader()
    { memset(this, 0, sizeof(CKYTXHeader)); }
    inline quint32 getDataLength()  { return getQuint32(nDataLength); }
    inline quint64 getTimeStamp()   { return getQuint64(nTimeStamp); }
    inline bool getEncrypt()        { return nEncrypt > 0 ? true : false; }
    inline quint16 getVerifyCode()  { return getQuint16(nVerifyCode); }

public:
	quint8 nHeaderID[4];        //协议识别头
    quint8 nVersion;            //版本号
    quint8 nCommand;            //指令类型：101~106
    quint8 nDataLength[4];      //报文头后数据长度
    quint8 nReserve[4];         //预留
    quint8 nTimeStamp[8];       //时间戳
    quint8 nEncrypt;            //是否加密 0否1是
    quint8 nVerifyCode[2];      //校验码
};

//指令类型101 测点列表
class CKYTXTags : public CKYTXBase
{
public:
	CKYTXTags()	{ nFunction = 0; }
	quint8 nFunction;
};

//测点列表 点表校验
class CKYTXTagsCheck : public CKYTXTags
{
public:
    CKYTXTagsCheck()
    { memset(this, 0, sizeof(CKYTXTagsCheck)); }
    inline quint32 getTagsNum()     { return getQuint32(nTagsNum); }
    inline quint16 getCheckCode()   { return getQuint16(nCheckCode); }
private:
    quint8 nTagsNum[4];     //测点数量
	quint8 nCheckCode[2];	//校验码
};

//测点列表 测点信息
class CKYTXTagsInfo : public CKYTXTags
{
public:
	CKYTXTagsInfo() 
    { memset(this, 0, sizeof(CKYTXTagsInfo)); }
    inline quint16 getTotalNum()    { return getQuint16(nTotalNum); }
    inline quint16 getRemainNum()   { return getQuint16(nRemainNum); }
    inline quint16 getTagsNum()     { return getQuint16(nTagsNum); }

private:
    quint8 nTotalNum[2];    //测点总数
    quint8 nRemainNum[2];   //剩余未发送总数
    quint8 nTagsNum[2];     //当前包测点个数
};

//指令类型102 测点实时数据
class CKYTXRealData : public CKYTXBase
{
public:
	CKYTXRealData()
    { memset(this, 0, sizeof(CKYTXRealData)); }
    inline quint32 getIndex()       { return getQuint32(nIndex); }
    inline quint8  getQuality()     { return nQuality; }
    inline qint64  getTime()        { return getQint64(nTime); }
    inline quint16 getStrLength()   { return getQuint16(nStrLength); }
    inline quint64 getData()
    {
        quint64 nRtn = 0;
        memcpy(&nRtn, nData, sizeof(quint64));
        return nRtn;
    }

public:
	quint8 nIndex[4];		//测点索引
	quint8 nQuality;		//测点质量
	quint8 nTime[8];		//时间戳
    quint8 nStrLength[2];	//字符串长度
    quint8 nData[8];        //数据值
};

//指令类型103 报警数据
class CKYTXWarning
{
public:
	CKYTXWarning() { nType = 0; }
	quint16 nType;
};

//指令类型104 状态数据
class CKYTXStatus : public CKYTXBase
{
public:
	CKYTXStatus()
    { memset(this, 0, sizeof(CKYTXStatus)); }

    inline double   getCPUUsage()    { return getDouble(nCPUUsage); }
    inline double   getRAMUsage()    { return getDouble(nRAMUsage); }
    inline double   getDiskUsage()   { return getDouble(nDriveUsage); }
    inline double   getTemperature() { return getDouble(nTemperature); }
    inline quint16  getDriverNum()   { return getQuint16(nDriverNum); }

private:
	quint8 nCPUUsage[4];		//CP占用
	quint8 nRAMUsage[4];		//内存占用
	quint8 nDriveUsage[4];		//硬盘占用
	quint8 nTemperature[4];		//设备温度
	quint8 nDriverNum[2];		//驱动数量
};

//指令类型105 历史数据上传
class CKYTXHistory : public CKYTXBase
{
public:
	CKYTXHistory()
    { memset(this, 0, sizeof(CKYTXHistory)); }
    inline quint16  getTagNum()         { return getQuint16(nTagNum); }
    inline quint16  getRecordedNum()    { return getQuint16(nRecordedNum); }
    inline quint16  getUnrecordedNum()  { return getQuint16(nUnrecordedNum); }

private:
	quint8 nTagNum[2];			//测点数量
	quint8 nRecordedNum[2];		//已补录数量
    quint8 nUnrecordedNum[2];	//待补录数量
};

//指令类型106 日志信息
class CKYTXLog
{
public:
	CKYTXLog()
    { memset(this, 0, sizeof(CKYTXLog)); }
	quint8 nLength[4];	//日志长度
};

#endif // TCPSTRUCT_H
